// quantDll.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "quantDll.h"
#include "../../CppClient/client/EClient.h"
#include "../../CppClient/client/EClientSocket.h"

#include <fstream>
#include <iostream>

#define USSTOCKATSMART__MIDPRICE 1
#define USSTOCKATSMART__FOREX_CASH_QUANTITY 2
#define SIMPLEFUTURE__MARKET 3
#define USSTOCKATSMART__FOREX_CASH_QUANTITY__STOP 4

#define VI_KEY 0
#define VI_VALUE 1

std::string myFilePath();
std::string path = myFilePath();
std::ofstream outFile(path,std::ios::trunc);

TCCBUF tccBuf; //zero initilaztion , since this form { .pErrorId = nullptr } does not work.
TCCBUF& rTccBuf = tccBuf;

TestCppClient tcc(outFile,rTccBuf);

std::string myFilePath()
{
	std::string path;
	TCHAR s[BUFSIZ];
	DWORD dwRet = GetCurrentDirectory(BUFSIZ, s);

	path = s;
	path = path.append("\\myquantdll.log");
	return path;
}

const std::vector<std::string> split(const std::string& str, const std::string& pattern) {
	std::vector<std::string> result;
	std::string::size_type begin, end;

	end = str.find(pattern);
	begin = 0;

	while (end != std::string::npos) {
		if (end - begin != 0) {
			result.push_back(str.substr(begin, end - begin));
		}
		begin = end + pattern.size();
		end = str.find(pattern, begin);
	}

	if (begin != str.length()) {
		result.push_back(str.substr(begin));
	}
	return result;
}

bool tws_connect(const char * host, int port, int clientId)
{

	bool bRes = tcc.connect(host, port, clientId);

	if (bRes) {
		outFile << "quantDll: connected" << std::endl;
	}
	else {
		outFile << "quantDll:not connected " << std::endl;
	}

	return bRes;
}

void tws_disconnect()
{
	tcc.disconnect();
}

bool tws_isConnected()
{
	bool bRes = tcc.isConnected();
	return bRes;
}

void tws_processMsgs()
{
	outFile << "quantDll: tws_processMsgs" << std::endl;
	tcc.processMessages();
}

void tws_waitForSignal()
{
	outFile << "quantDll: entered tws_waitForSignal" << std::endl;
	tcc.m_osSignal.waitForSignal();
}

void tws_readerProcessMsgs()
{
	outFile << "quantDll: entered tws_readerProcessMsgs" << std::endl;
	tcc.m_pReader->processMsgs();
}


//void tws_reqManagedAccounts(int *errorId, int* errorCode)
//{
//	tcc.m_pClient->reqManagedAccts();
//}

char* tws_getManagedAccounts()
{
	char *p = tcc.m_tccBuf.pManagedAccts;
	if (nullptr == p)
		outFile << "quantDll-getManagedAccount: not retrieved yet" << std::endl;
	else
		outFile << "quantDll-getManagdAccount :" << p << std::endl; 
	return p ;
}

void tws_reqAccountUpdates()
{
	tcc.m_state =  ST_ACCOUNTUPDATE;
}

char* tws_updateAccountValue()
{
	char *p = tcc.m_tccBuf.pAccountValue;
	if (nullptr == p)
		outFile << "quantDll-updateAccountValue: not retrieved yet" << std::endl;
	else
		outFile << "quantDll-updateAccountValue:" << p << std::endl;
	return p;
}

void tws_reqAccountSummary()
{
	tcc.m_state = ST_ACCOUNTSUMMARY;
}

char* tws_updateAccountSummary()
{
	char *p = tcc.m_tccBuf.pAccountSummary;
	if (nullptr == p)
		outFile << "quantDll-updateAccountSummary: not retrieved yet" << std::endl;
	else
		outFile << "quantDll-updateAccountSummary:" << p << std::endl;
	return p;
}


void tws_placeOrder(const char* pContract, const char* pOrder)
{
	std::string pCon(pContract), pOrd(pOrder);
	std::vector<std::string> vsCon = split(pCon,",");
	std::vector<std::string> vsOrd = split(pOrd,",");
	std::vector<std::string> vsItem;

	size_t iSize = vsCon.size();
	int i = 0;

	outFile << "tws_placeOrder: contract=" << pCon << std::endl;
	outFile << "tws_placeOrder: order=" << pOrd << std::endl;

	for (i = 0; i < iSize; i++)
	{
		vsItem = split(vsCon[i], ":");
		outFile << "vsContract...\n";
		outFile << "vsItem-key=" << vsItem[0] << ",vsItem-value=" << vsItem[1] << std::endl;
	
		if (vsItem[VI_KEY] == "symbol")
			tcc.m_tccBuf.tb_contract.symbol = vsItem[VI_VALUE];
		else if (vsItem[VI_KEY] == "secType")
			tcc.m_tccBuf.tb_contract.secType = vsItem[VI_VALUE];
		else if (vsItem[VI_KEY] == "currency")
			tcc.m_tccBuf.tb_contract.currency = vsItem[VI_VALUE];
		else if (vsItem[VI_KEY] == "exchange")
			tcc.m_tccBuf.tb_contract.exchange = vsItem[VI_VALUE];
		else if (vsItem[VI_KEY] == "lastTradeDateOrContractMonth")
			tcc.m_tccBuf.tb_contract.lastTradeDateOrContractMonth = vsItem[VI_VALUE];
		else if (vsItem[VI_KEY] == "strike")
			tcc.m_tccBuf.tb_contract.strike = stod(vsItem[VI_VALUE]);
		else if (vsItem[VI_KEY] == "right")
			tcc.m_tccBuf.tb_contract.right = vsItem[VI_VALUE];
		else if (vsItem[VI_KEY] == "multiplier")
			tcc.m_tccBuf.tb_contract.multiplier = vsItem[VI_VALUE];
		else if (vsItem[VI_KEY] == "tradingClass")
			tcc.m_tccBuf.tb_contract.tradingClass = vsItem[VI_VALUE];
		//else if (vsItem[VI_KEY] == "")
		//	tcc.m_tccBuf.tb_contract. = vsItem[VI_VALUE];
	}

	iSize = vsOrd.size();

	for (i = 0; i < iSize; i++)
	{
		vsItem = split(vsOrd[i],":");
		outFile << "vsOrder...\n";
		outFile << "vsItem-key=" << vsItem[0] << ",vsItem-value=" << vsItem[1] << std::endl;

		if (vsItem[VI_KEY] == "action")
			tcc.m_tccBuf.tb_order.action = vsItem[VI_VALUE];
		else if (vsItem[VI_KEY] == "orderType")
			tcc.m_tccBuf.tb_order.orderType = vsItem[VI_VALUE];
		else if (vsItem[VI_KEY] == "cashQty")
			tcc.m_tccBuf.tb_order.cashQty = std::stol(vsItem[VI_VALUE]);
		else if (vsItem[VI_KEY] == "lmtPrice")
			tcc.m_tccBuf.tb_order.lmtPrice = std::stod(vsItem[VI_VALUE]);
		else if (vsItem[VI_KEY] == "totalQuantity")
			tcc.m_tccBuf.tb_order.totalQuantity = std::stol(vsItem[VI_VALUE]);
		else if (vsItem[VI_KEY] == "auxPrice")
			tcc.m_tccBuf.tb_order.auxPrice = std::stod(vsItem[VI_VALUE]);
	}

	//switch (iIndex)
	//{
	//	case USSTOCKATSMART__MIDPRICE:
	//		// usStockatSMART
	//		tcc.m_tccBuf.tb_contract.symbol = vsCon[0];
	//		tcc.m_tccBuf.tb_contract.secType = vsCon[1];
	//		tcc.m_tccBuf.tb_contract.currency = vsCon[2];
	//		tcc.m_tccBuf.tb_contract.exchange = vsCon[3];
	//		tcc.m_tccBuf.tb_order.action = vsOrd[0];
	//		tcc.m_tccBuf.tb_order.orderType = "MIDPRICE";
	//		tcc.m_tccBuf.tb_order.totalQuantity = std::stol(vsOrd[1]);
	//		tcc.m_tccBuf.tb_order.lmtPrice = std::stod(vsOrd[2]);
	//		break;
	//	case USSTOCKATSMART__FOREX_CASH_QUANTITY:
	//		tcc.m_tccBuf.tb_contract.symbol = vsCon[0];
	//		tcc.m_tccBuf.tb_contract.secType = vsCon[1];
	//		tcc.m_tccBuf.tb_contract.currency = vsCon[2];
	//		tcc.m_tccBuf.tb_contract.exchange = vsCon[3];
	//		tcc.m_tccBuf.tb_order.action = vsOrd[0];
	//		tcc.m_tccBuf.tb_order.orderType = "LMT";
	//		tcc.m_tccBuf.tb_order.cashQty= std::stol(vsOrd[1]);
	//		tcc.m_tccBuf.tb_order.lmtPrice = std::stod(vsOrd[2]);
	//		break;
	//	case SIMPLEFUTURE__MARKET:
	//		tcc.m_tccBuf.tb_contract.symbol = vsCon[0];
	//		tcc.m_tccBuf.tb_contract.secType = vsCon[1];
	//		tcc.m_tccBuf.tb_contract.currency = vsCon[2];
	//		tcc.m_tccBuf.tb_contract.exchange = vsCon[3];
	//		tcc.m_tccBuf.tb_contract.lastTradeDateOrContractMonth= vsCon[4];
	//		tcc.m_tccBuf.tb_order.action = vsOrd[0];
	//		tcc.m_tccBuf.tb_order.orderType = "MKT";
	//		tcc.m_tccBuf.tb_order.totalQuantity = std::stol(vsOrd[1]);
	//		break;
	//	case USSTOCKATSMART__FOREX_CASH_QUANTITY__STOP:
	//		tcc.m_tccBuf.tb_contract.symbol = vsCon[0];
	//		tcc.m_tccBuf.tb_contract.secType = vsCon[1];
	//		tcc.m_tccBuf.tb_contract.currency = vsCon[2];
	//		tcc.m_tccBuf.tb_contract.exchange = vsCon[3];
	//		tcc.m_tccBuf.tb_order.action = vsOrd[0];
	//		tcc.m_tccBuf.tb_order.orderType = "STP";
	//		tcc.m_tccBuf.tb_order.totalQuantity = std::stol(vsOrd[1]);
	//		tcc.m_tccBuf.tb_order.auxPrice = std::stod(vsOrd[2]);
	//		break;
	//}
	
	
	tcc.m_state = ST_PLACEORDER;
}

char* tws_orderStatus()
{
	char *p = tcc.m_tccBuf.pOrderStatus;
	if (nullptr == p)
		outFile << "quantDll-orderStatus: not retrieved yet" << std::endl;
	else
		outFile << "quantDll-orderStatus:" << p << std::endl;
	return p;
}

void tws_cancelOrder(OrderId id)
{
	outFile << "quantDll-cancelOrder entered" << std::endl;
	tcc.m_tccBuf.orderIdToCancel = id;
	tcc.m_state = ST_CANCELORDER;
}
